package zhoufu.sz.sanxiao_check.net;

import android.content.Context;
import android.graphics.Bitmap;
import android.text.TextUtils;
import android.webkit.URLUtil;

import com.google.gson.Gson;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.UnknownFormatConversionException;

import javax.inject.Singleton;

import okhttp3.MediaType;
import okhttp3.RequestBody;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
import rx.subscriptions.CompositeSubscription;
import zhoufu.sz.sanxiao_check.inject.RetrofitQualifier;
import zhoufu.sz.sanxiao_check.models.BaseModel;
import zhoufu.sz.sanxiao_check.models.GrandCountModel;
import zhoufu.sz.sanxiao_check.models.ReseauModel;
import zhoufu.sz.sanxiao_check.models.StreetInfoModel;
import zhoufu.sz.sanxiao_check.models.StreetListModel;
import zhoufu.sz.sanxiao_check.models.User;
import zhoufu.sz.sanxiao_check.utils.DESUtil;
import zhoufu.sz.sanxiao_check.utils.FileUtils;
import zhoufu.sz.sanxiao_check.utils.ImageUtils;

/**
 * 项目：
 * 时间： 2016/6/20 9:13
 * 人员： hyc
 * 功能：
 */
@Singleton
public class RequestRepository extends RequestHelper
{

    protected MapBuilder _mapBuilder;

    protected Gson                  _gson;
    private   CompositeSubscription _compositeSubscription;


    public RequestRepository(Context Context, @RetrofitQualifier Gson gson)
    {
        super(Context);
        _mapBuilder = MapBuilder.getInstance();
        _compositeSubscription = new CompositeSubscription();
        _gson = gson;
    }

    /**
     * 设置Gson
     */
    public void setGson(Gson gson)
    {
        _gson = gson;
    }

    public Gson getGson()
    {

        return _gson;
    }

    //实时上传经纬度
    public Subscription AddPlease(double lon, double lat, RequestCallBack back)
    {

        if ( back == null )
        {
            throw new NullPointerException("RequestCallBack can't be empty");
        }
        String map = DESUtil
                .EncryptAsToMap(_mapBuilder.creatationHashMap().Longitude(lon).Latitude(lat)
                        .UserID(User.readUser().getID()).UserName(User.readUser().getLoginName())
                        .build());
        Observable<String> loginLatest  = getStringObservable(map, "AddPlease");
        Subscription       subscription = subChainWithCallBack(loginLatest, BaseModel.class, back);
        _compositeSubscription.add(subscription);
        return subscription;
    }

    /**
     * 登录
     */
    public Subscription login(User user, String uuid, String vname, RequestCallBack back)
    {

        if ( back == null )
        {
            throw new NullPointerException("RequestCallBack can't be empty");
        }
        String map = DESUtil
                .EncryptAsToMap(_mapBuilder.creatationHashMap().UserName(user.getName())
                        .Password(user.getPassword())
                        .IMEI(uuid).Version(vname).build());
        Observable<String> loginLatest  = getStringObservable(map, "LoginLatest");
        Subscription       subscription = subChainWithCallBack(loginLatest, user.getClass(), back);
        _compositeSubscription.add(subscription);
        return subscription;
    }

    //修改密码
    public Subscription UpdatePassword(String pass1, String pass2, RequestCallBack<BaseModel> back)
    {
        if ( back == null )
        {
            throw new NullPointerException("RequestCallBack can't be empty");
        }
        String map = DESUtil
                .EncryptAsToMap(_mapBuilder.creatationHashMap().UserID(User.readUser().getID())
                        .OldPassword(pass1).NewPassword(pass2).build());
        Observable<String> loginLatest  = getStringObservable(map, "UpdatePassword ");
        Subscription       subscription = subChainWithCallBack(loginLatest, BaseModel.class, back);
        _compositeSubscription.add(subscription);
        return subscription;
    }

    public Subscription GetGridList(RequestCallBack<ReseauModel> back)
    {

        if ( back == null )
        {
            throw new NullPointerException("RequestCallBack can't be empty");
        }
        String map = DESUtil
                .EncryptAsToMap(_mapBuilder.creatationHashMap().CID(User.readUser().getCharge_ID())
                        .build());
        Observable<String> loginLatest = getStringObservable(map, "GetGridList");
        Subscription subscription = subChainWithCallBack(loginLatest, ReseauModel.class,
                back);
        _compositeSubscription.add(subscription);
        return subscription;
    }


    //Status:状态 0：全部 1 未检查 2 已检查 3 待复查 4 已复查
    //District:片区ID(没有为0)
    public Subscription GetGrade(int Status, String District, RequestCallBack<GrandCountModel> back)
    {

        if ( back == null )
        {
            throw new NullPointerException("RequestCallBack can't be empty");
        }
        String map = DESUtil
                .EncryptAsToMap(_mapBuilder.creatationHashMap().CID(User.readUser().getCharge_ID())
                        .Status(Status).District(District + "")
                        .build());
        Observable<String> loginLatest = getStringObservable(map, "GetGrade");
        Subscription subscription = subChainWithCallBack(loginLatest, GrandCountModel.class,
                back);
        _compositeSubscription.add(subscription);
        return subscription;
    }

    //
    public Subscription GetStreetByPagerNew(int Status,String type, String Grade, String Name, String District,
            String Address, String Place_No, String Building_No, int PageIndex,
            RequestCallBack<StreetListModel> back)
    {

        if ( back == null )
        {
            throw new NullPointerException("RequestCallBack can't be empty");
        }
        String map = DESUtil
                .EncryptAsToMap(
                        _mapBuilder.creatationHashMap().Status(Status).Grade(Grade).Name(Name)
                                .District(District)
                            .Type(type)
                                .Address(Address).Place_No(Place_No).Building_No(Building_No)
                                .PageIndex(PageIndex).PageSize().CID(User.readUser().getCharge_ID())
                                .build());
        Observable<String> loginLatest = getStringObservable(map, "GetStreetByPagerNew");
        Subscription subscription = subChainWithCallBack(loginLatest, StreetListModel.class,
                back);
        _compositeSubscription.add(subscription);
        return subscription;
    }


    public Subscription GetStreetByBuildingNo(String RID, String SID,
            String Building_No,
            RequestCallBack<StreetInfoModel> back)
    {

        if ( back == null )
        {
            throw new NullPointerException("RequestCallBack can't be empty");
        }
        String map = DESUtil
                .EncryptAsToMap(
                        _mapBuilder.creatationHashMap().RID(RID).SID(SID).Building_No(Building_No)
                                .CID(User.readUser().getCharge_ID())
                                .build());
        Observable<String> loginLatest = getStringObservable(map, "GetStreetInfo2");
        Subscription subscription = subChainWithCallBack(loginLatest, StreetInfoModel.class,
                back);
        _compositeSubscription.add(subscription);
        return subscription;
    }

    //更新门头照片
    public Subscription UpdatePhotoInfo(final String RID, final String SID,
            final int PhotoType, String PhotoPath,
            RequestCallBack<BaseModel> back)
    {
        Observable<String> addAgreementNew = _UpLoadImage(PhotoPath)
                .switchMap(new Func1<String, Observable<String>>()
                {
                    @Override
                    public Observable<String> call(String s)
                    {
                        String map = DESUtil
                                .EncryptAsToMap(
                                        _mapBuilder.creatationHashMap().RID(RID).SID(SID)
                                                .PhotoType(PhotoType)
                                                .PhotoPath(s)
                                                .build());
                        return getStringObservable(map, "UpdatePhotoInfo");
                    }
                });
        return addSubscribe(subChainWithCallBack(addAgreementNew, BaseModel.class, back));
    }

    //保存空铺信息
    public Subscription UpdateEmptyShopInfo(String RID, int IsLive,
            String People_Num,
            RequestCallBack<BaseModel> back)
    {
        if ( back == null )
        {
            throw new NullPointerException("RequestCallBack can't be empty");
        }
        String map = DESUtil
                .EncryptAsToMap(
                        _mapBuilder.creatationHashMap().RID(RID).IsLive(IsLive)
                                .People_Num(People_Num)
                                .build());
        Observable<String> loginLatest = getStringObservable(map, "UpdateEmptyShopInfo");
        Subscription subscription = subChainWithCallBack(loginLatest, BaseModel.class,
                back);
        _compositeSubscription.add(subscription);
        return subscription;
    }


    //保存空铺信息
    public Subscription StreeClose(String SID,
            RequestCallBack<BaseModel> back)
    {
        if ( back == null )
        {
            throw new NullPointerException("RequestCallBack can't be empty");
        }
        String map = DESUtil
                .EncryptAsToMap(
                        _mapBuilder.creatationHashMap().SID(SID)
                                .build());
        Observable<String> loginLatest = getStringObservable(map, "StreeClose");
        Subscription subscription = subChainWithCallBack(loginLatest, BaseModel.class,
                back);
        _compositeSubscription.add(subscription);
        return subscription;
    }

    public Subscription subChainWithCallBack(Observable<String> observable, final Class clazz,
            final RequestCallBack back)
    {
        return observable.subscribeOn(Schedulers.io()).doOnSubscribe(new Action0()
        {
            @Override
            public void call()
            {
                back.onPullStart();
            }
        }).doOnUnsubscribe(new Action0()
        {
            @Override
            public void call()
            {
                back.onPullEnd();
            }
        }).subscribeOn(AndroidSchedulers
                .mainThread()).subscribeOn(Schedulers.io()).map(new Func1<String, Object>()
        {
            @Override
            public Object call(String s)
            {
                System.out.println("s = " + s);
                Object json = _gson.fromJson(s, clazz);
                if ( json == null )
                {
                    throw new UnknownFormatConversionException("clazz is wrong !!");
                }
                return json;
            }
        }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<Object>()
        {
            @Override
            public void onCompleted()
            {
                back.onPullEnd();
            }

            @Override
            public void onError(Throwable e)
            {
                back.onPullFailud(e);
            }

            @Override
            public void onNext(Object us)
            {
                back.onPullSuccessed(us);
            }
        });
    }




    public void onDestory()
    {
        if ( _compositeSubscription.hasSubscriptions() )
        {
            _compositeSubscription.clear();
        }
    }

    public void unSub(Subscription target)
    {
        if ( _compositeSubscription.hasSubscriptions() && null != target )
        {
            _compositeSubscription.remove(target);
        }
    }

    public Subscription addSubscribe(Subscription subscription)
    {
        if ( null == _compositeSubscription )
        {
            _compositeSubscription = new CompositeSubscription();
        }
        _compositeSubscription.add(subscription);
        return subscription;
    }

    public Observable<String> getStringObservable(String reqData, String getWangGe)
    {
        return provideApiService().post3(getWangGe, reqData);
    }

    public Observable<String> _UploadImageOne(String path)
    {
        if ( zhoufu.sz.sanxiao_check.utils.TextUtils.isEmpty(path) )
        {
            return Observable.just("");
        } else
        {
            return Observable.just(path).map(new Func1<String, String>()
                    {
                        @Override public String call(String s)
                        {
                            if ( URLUtil.isHttpUrl(s) )
                            {
                                return s;
                            } else
                            {
//                              VolleyImageUtils.compress(s, 1280, 720, 80);
                                String compress = compress(new String[]{s});
                                RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), new File(compress.split(",")[0]));
                              try {
                                retrofit2.Response<String> response =
                                    provideApiService2().postUploadify(requestBody).execute();
                                if(response.isSuccessful()) {
                                  return response.body();
                                }
                              }catch (Exception e){
                                e.printStackTrace();
                              }

                            }
                            return null;
                        }
                    });
        }
    }

    /**
     * 压缩图片
     *
     * @param rawImgs 以逗号分隔开的图片路径字符串
     * @return 压缩好的多张图片间以逗号分隔开的字符串
     */
    public Observable<String> _UpLoadImage(String rawImgs)
    {
        if ( null == rawImgs )
        {
            rawImgs = "";
        }
        String[] imgs = rawImgs.split(",");
        return Observable.just(imgs)
                .subscribeOn(Schedulers.newThread())
                .map(new Func1<String[], String>()
                {
                    @Override
                    public String call(String[] strings)
                    {
                        //非主线程
                        String   upLoaded = "";
                        String[] paths    = new String[strings.length];

                        for (int i = 0; i < strings.length; i++)
                        {
                            //如果 字符串是 http 格式 将其拼接到 uploaded中
                            if ( URLUtil.isHttpUrl(strings[i]) )
                            {
                                upLoaded += strings[i] + ",";
                            } else
                            {
                                //如果不是 放入 paths中【】；
                                paths[i] = strings[i];
                            }
                        }
                        //压缩图片
                        String compress = compress(paths);
                        if ( TextUtils.isEmpty(compress) )
                        {
                            return upLoaded;
                        }

                        //拿到图片压缩后的地址，将其上传到服务器
                        String[]         files    = compress.split(",");
                        int              length   = files.length;
                        List<String>     strList  = Arrays.asList(files);
                        Iterator<String> iterator = strList.iterator();
                        int              position = 0;
                        while (iterator.hasNext())
                        {
                            String next = iterator.next();
                          RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), new File(next));
                          try {
                            retrofit2.Response<String> response =
                                provideApiService2().postUploadify(requestBody).execute();
                            if(response.isSuccessful()){
                              String string = response.body();
                              if ( !TextUtils.isEmpty(string) )
                              {
                                if ( iterator.hasNext() )
                                {
                                  upLoaded += ( string + "," );
                                } else
                                {
                                  upLoaded += string;
                                }
                              }
                            }
                          } catch (IOException e) {
                            e.printStackTrace();
                          }
                        }
                        return upLoaded;
                    }
                });
    }


    /**
     * 压缩图片
     *
     * @param path 未压缩前图片地址
     * @return 压缩后图片集合, 用","号分开
     */
    private String compress(String[] path)
    {
        String paths = null;

        for (int i = 0; i < path.length; i++)
        {
            String p = path[i];
            if ( TextUtils.isEmpty(p) || "无".equals(p) )
            {
                //如果 字符串为空 则跳过
                continue;
            }
            Bitmap bitmap = ImageUtils.getBitmap(path[i], 400, 800);
            String s      = FileUtils.getCacheDir() + "UpCache/";
            FileUtils.createDirs(s);
            String upPath = s + "temp" + System.currentTimeMillis() + ".jpg";
            ImageUtils.runPress(upPath, bitmap);
            if ( i == 0 )
            {
                paths = upPath + ",";//尾部接逗号
            } else
            {
                paths = paths + upPath + ",";
            }
        }
        return paths;
    }
}
